package com.apobates.forum.toro.core;

import java.util.HashMap;
import java.util.Map;

/**
 * 表达式
 * 使用限制:
 * 1)可选项不可以是连续的sequence.
 *   例:sequence=1可选,sequence=2不可以是可选的
 * 2)基于分隔符的不同来定义取值的边界. 开始分隔符和结束分隔符不能是一样的.
 *   例: sequence=1的分隔符:(<)sequence=2的分隔符不可以是:(<)
 * 3)基于边界规则. 分隔符必需是成对的,不能有缺失.
 *   例: sequence=1有分隔符.sequence=2不能缺少分隔符
 * 4)自定义Corner时即使某个word是可选的.表达式中其分隔符也必需存在.
 *   例: {id:long}这是全匹配.若long是可选的不能写成: {id 正确的是: {id}
 * 5)sequence值必须从0开始,每个word依次递增(+1).中间不能间断
 *   例: word1.sequence = 0, word2.sequence = 2
 */
public class Express {
    private Map<String,Corner> data = new HashMap<>();

    private Express() {
    }

    /**
     * 使用指定的词语[/属性]Corner来构建实例
     * 只供构建器调用.不对外开放
     * @param data key = 词语[/属性], value=词语[/属性]的描述性角注
     */
    private Express(Map<String, Corner> data) {
        this.data = data;
    }

    /**
     * 返回一个空表达式实例
     * @return
     */
    public static Express getInstance(){
        return new Express();
    }

    /**
     * 创建一个词语[/属性]构建器
     * @param word 词语[/属性]
     * @return
     */
    public Builder word(String word){
        return new Builder(word);
    }

    private Map<String, Corner> getData() {
        return data;
    }

    /**
     * 使用对象的Class作为表达式的构造基顾
     * @param beanClass
     * @return
     * @param <T>
     */
    public <T> BeanParser<T> build(Class<T> beanClass){
        return new BeanParser<>(beanClass, data);
    }

    /**
     * 使用对象实例作为表达式的构造基顾
     * @param instance
     * @return
     * @param <T>
     */
    public <T> BeanParser<T> build(T instance){
        return new BeanParser<>(instance, data);
    }

    /**
     *
     */
    public class Builder{
        private final String word;
        //private Corner corner;

        public Builder(String word){
            this.word = word;
        }

        /**
         * 设置词语[/属性]的描述性角注
         * @param corner
         * @return
         */
        public Express corner(Corner corner){
            Map<String, Corner> tmp = getData();
            tmp.put(word, corner);
            Map<String, Corner> data = new HashMap<>(tmp);
            return new Express(data);
        }
    }
}
